<?php
	class Durak extends CI_Controller{
		
		public $PLAYER_ONE = 1;
		public $PLAYER_TWO = 2;
	
		public $playerOne;
		public $playerTwo;
		public $deck;
		
		public $currentPlayer;
		public $opponentPlayer;
		
		function __construct(){
			parent::__construct();
			$this->load->library('cards');
			$this->deck = new cards();
			$this->playerOne = new player();
			$this->playerTwo = new player();
			
			$this->playerOne->initPlayer($this->PLAYER_ONE);
			$this->playerTwo->initPlayer($this->PLAYER_TWO);
		}
		
		function index(){
			$this->setSession();
			$this->playAgain();
		}
		
		function play(){
			$player = $this->getCurrentPlayer();
			$nextPlayer = $this->getNextPlayer($player);
			
			$data['player'] 			= $this->getPlayerIds($player, $nextPlayer);
			$data['hand'] 				= $this->getHands($player, $nextPlayer);
			$data['score'] 				= $this->getScores();
			$data['shuffle']	 		= $this->getShuffles();
			$data['status'] 			= $this->session->userdata('status');
			$data['deckCount']			= $this->getDeckCount();
			$data['workSpace'] 			= $this->session->userdata('workSpace');
			$data['trump'] 				= $this->getTrump();
			$data['attackCount'] 		= $this->session->userdata('attackCount');
			$data['option'] 			= $this->session->userdata('option');
			$data['alert']		 		= $this->session->userdata('alert');
			$data['parts'] 				= array('parts/info', 'parts/workspace', 'parts/player');
			
			$this->load->view('templates/header', $data);
			$this->load->view('durak_view', $data);
		}
		
		function setSession(){
			$session_data = array(
				'deck'					=> [],			// array of cards object (contains 1 object)
				'status'				=> '',			// turn status (Attack or Defend)
				'workSpace'				=> [],			// main table
				'data'					=> [],			// temp storage of playerHand after unset
				'attackCount'			=> 0,
				'option'				=> false,
				'theWinner'				=> 0,			
				'surrender'				=> false,
				'alert'					=> '',
				'showHide'				=> '',
				'currentPlayer'			=> [],
				'allPlayers'			=> []			// array of player objects
			);
			$this->session->set_userdata($session_data);
		}
		
		function playAgain(){
			$data['score'] = $this->getScores();
			$data['theWinner'] = $this->session->userdata('theWinner');
			$data['status'] = $this->session->userdata('status');
			$data['alert'] = $this->session->userdata('alert');
			
			$this->load->view('templates/header', $data);
			$this->load->view('durak_intro', $data);
		}
		
		function initializePlay($win=false, $id=false){
			$this->reset();
			$this->playerOne->shuffleOption();
			$this->playerTwo->shuffleOption();
			
			$allPlayers = array(
						$this->playerOne,
						$this->playerTwo
						);
			
			$this->session->set_userdata('allPlayers', $allPlayers);
			$this->setDeck($this->deck->getAllDeck());
			
			$this->setOrder($win, $id);
			
			redirect('letsplaydurak');
		}
		
		function reset(){
			$this->deck->initShuffleDeck();
			$this->session->set_userdata('workSpace', []);
			$this->playerOne->resetPlayer();
			$this->playerTwo->resetPlayer();
			$this->playerOne->playHand($this->deck);
			$this->playerTwo->playHand($this->deck);
			$this->deck->initTrump();
		}
		
//=====================================================================================================================================================================================
// GET & SET METHODS
//=====================================================================================================================================================================================
		function getScores(){
			$array = $this->session->userdata('allPlayers');
			$scores = [0,0];
			
			if(!empty($array))
				$score = [];
				for($i=0; $i<2; $i++){
					if($this->session->userdata('allPlayers')){
						$player = $this->fixObject($this->session->userdata('allPlayers')[$i]);
						array_push($score, $player->getScore());
					}
				}
			return $scores;
		}
		
		function getPlayerIds($player, $nextPlayer){
			$playerIds = array('currentPlayer' => $player->getPlayer(), 'nextPlayer' => $nextPlayer->getPlayer());
			return $playerIds;
		}
		
		function getHands($player, $nextPlayer){
			$hands =  array('currentHand' => $player->getHand(), 'nextHand' => $nextPlayer->getHand());
			return $hands;
		}
		
		function getShuffles(){
			$shuffles = array('currentShuffle' => $this->playerOne->getShuffle(), 'opponentShuffle' => $this->playerTwo->getShuffle());
			return $shuffles;
		}
		
		function setDeck($deck){
			$this->session->set_userdata('deck', $deck);
		}
		
		function getDeck(){
			return $this->session->userdata('deck');
		}
		
		function getTrump(){
			return $this->getDeck()['trump'];
		}
		
		function getDeckCount(){
			return count($this->getDeck()['deck']);
		}

		function setTurn($stat){
			if($stat=='Defend')
				$this->session->set_userdata('status', 'Defend');
			elseif($stat=='Attack')
				$this->session->set_userdata('status', 'Attack');
		}
		
		function setWinner($id){
			$this->session->set_userdata('theWinner', $id);
			
			$player = $this->getPlayerById($id);
			$player->increaseScore();
			$this->session->set_userdata('alert', 'Player '.$id.' wins!');
			$this->setAllPlayers($player);
			
			redirect('gameover');
		}
		
		function setAllPlayers($player){
			$array = array($player, $this->getNextPlayer($player));
			$allPlayers = [];

			for($i=0; $i<2; $i++){
				if(3%($array[$i]->getPlayer()) == $i)					// If player id is according to order (ex. [1,2] == [0,1])
					array_push($allPlayers, $array[$i]);				// store the players to temporary array accordingly
				else													// If not (ex. [2,1] != [0,1])
					array_unshift($allPlayers,$array[3%($i+1)]);		// stores the players in proper order (ex [2,1] => [1,2])
			}
			$this->session->set_userdata('allPlayers', $allPlayers);	// sets the session to the temporary array
		}
		
		function setCurrentPlayer($player){
			$this->session->set_userdata('currentPlayer', $this->fixObject($player));
		}
		
		function getCurrentPlayer(){
			return $this->fixObject($this->session->userdata('currentPlayer'));
		}
		
		function setNextPlayer($player){
			$this->session->set_userdata('currentPlayer', $this->getNextPlayer($player));
		}
		
		function getNextPlayer($player){
			$index = 3%($player->getPlayer()+1);
			return $this->fixObject($this->session->userdata('allPlayers')[$index]);
		}
		
		function getPlayerById($id){
			$index = 3%($id);
			return $this->fixObject($this->session->userdata('allPlayers')[$index]);
		}
		
		function setNextPlayerById($id){
			$this->session->set_userdata('currentPlayer', $this->getNextPlayerById($id));
		}
		
		function getNextPlayerById($id){
			$index = 3%($id+1);
			return $this->fixObject($this->session->userdata('allPlayers')[$index]);
		}
		
		function getNextPlayerIdById($id){
			return $this->getNextPlayerById($id)->getPlayer();
		}
		
//=====================================================================================================================================================================================
// RULES
//=====================================================================================================================================================================================
		function setOrder($hasWinner, $id){
			if($hasWinner){																	// Checks if there's a previous winner
				$player = $this->getPlayerById($id);
				$this->setCurrentPlayer($player);											// If there is, he attacks first
				$this->session->set_userdata('alert', 'Player '.$id.' attacks first!');
			}else{																			// If not
				$this->playerOne->trumpHand($this->deck);
				$this->playerTwo->trumpHand($this->deck);

				$fTemp = $this->playerOne->getTempTrumpValue();
				$sTemp = $this->playerTwo->getTempTrumpValue();
				$fTrumpFound = $this->playerOne->getTrumpFound();
				$sTrumpFound = $this->playerTwo->getTrumpFound();
				
				if($fTrumpFound && $sTrumpFound){									// if trump is found on both sides
					if($fTemp<$sTemp){												// compare the values
						$this->setCurrentPlayer($this->playerOne);							// if fTemp is lower, player 1 attacks first
						$this->session->set_userdata('alert', 'Player 1 has the lowest trump card, Player 1 attacks first!');
					}else{															// otherwise, player 2 attacks first
						$this->setCurrentPlayer($this->playerTwo);
						$this->session->set_userdata('alert', 'Player 2 has the lowest trump card, Player 2 attacks first!');
					}
				}elseif(!$fTrumpFound && !$sTrumpFound){							// if no trump is found, player 1 attacks first
					$this->setCurrentPlayer($this->playerOne);
					$this->session->set_userdata('alert', 'No trump was present on either hands, Player 1 attacks first!');
				}elseif($fTrumpFound && !$sTrumpFound){								// if trump is only found on player 1's hand, he attacks first
					$this->setCurrentPlayer($this->playerOne);
					$this->session->set_userdata('alert', "No trump was found on Player 2's hand. Player 1 attacks first!");
				}elseif(!$fTrumpFound && $sTrumpFound){								// if trump is only found on player 2's hand, he attacks first
					$this->setCurrentPlayer($this->playerTwo);
					$this->session->set_userdata('alert', "No trump was found on Player 1's hand. Player 2 attacks first!");
				}
			}
			
			$this->session->set_userdata('status', 'Attack');
		}
		
		function setAction($index){
			$status = $this->session->userdata('status');
			$attackCount = $this->session->userdata('attackCount');
			$player = $this->getCurrentPlayer();
			$data = $this->session->userdata('data');
			$temp = [];
			
			foreach($player->getHand() as $hand):			// Stores the player's hand to a temporary array
				array_push($temp, $hand);					// and resets it to player's hand
			endforeach;										// Why? Because the original player's hand is full of missing indexes due to unset
			
			$player->setHand($temp);
			
			if($status=='Attack')
				$this->attack($player, $index, $attackCount);

			elseif($status=='Defend')
				$this->defend($player, $index);
		}
		
		function attack($player, $index, $attackCount){
			$workSpace = $this->session->userdata('workSpace'); 
				
			if(empty($workSpace)){																// Checks if workspace is empty or not
				$player->setShuffle(false);
				$this->attacker($player, $index, $attackCount);									// Adds the card to workspace and remove it from hand
			} elseif(!empty($workSpace)) {														// If not empty
				for($i=0; $i<count($workSpace); $i++){ 											// Checks each card on the workspace if attack card's value matches any of theirs
					if($player->getHand()[$index]['value'] == $workSpace[$i]['value']){			// if found
						$this->attacker($player, $index, $attackCount);
						break;											
					}elseif($player->getHand()[$index]['value'] != $workSpace[$i]['value'])
						$this->session->set_userdata('alert', "Card is not of the same value!");
					}
				}
			redirect('letsplaydurak');
		}
		
		function attacker($player, $index, $attackCount){
			$deckCount = $this->getDeckCount();
			$workSpace = $this->session->userdata('workSpace');
			$hand = $player->getHand();
			
			if($attackCount<6){
				if(end($workSpace) != $hand[$index]){
					$this->addToWorkSpace($hand[$index]);			// Adds the card to workspace
					unset($hand[$index]);							// Removes the card from hand

					$player->setHand($hand);
					$this->setCurrentPlayer($player);
					
					$HandCount = $player->getHandCount();
					
					if($HandCount==0 && $deckCount==0)					// If player's hand and remaining cards = 0
						$this->setWinner($player->getPlayer());			// game over, player wins
					
					if(!$this->session->userdata('surrender')){			// If opponent didn't surrender
						$this->setNextPlayer($player);					// Game continues
						$this->setTurn('Defend');
					}
					$this->setAllPlayers($player);

					$this->session->set_userdata('alert', 'Player '.$player->getPlayer().' attacks!');
					$this->session->set_userdata('attackCount', $attackCount+1);
				}
			}else
				$this->session->set_userdata('alert', 'You have reached the maximum limit of attacks per turn');
		}
		
		function defend($player, $index){
			$workSpace = $this->session->userdata('workSpace');
			
			$suit = $this->getTrump()['suit'];
			$card = $player->getHand()[$index];
			
			if($card['suit']==$suit){										// Checks if defense card is trump
				if(end($workSpace)['suit']==$suit){							// Checks if attack card is suit
					if($card['value']>end($workSpace)['value'])				// If defense card value is higher than attack card's
						$this->defender($player, $index);					// this adds the card to the workspace and remove it from player's hand
					else
						$this->session->set_userdata('alert', 'Card is of lower value!');
				}else{														// Attack card is not suit
					$this->defender($player, $index);						// Add card to workspace and remove from hand
				}
				
			}elseif($card['suit']==end($workSpace)['suit']){				// If defense card is not trump
				if($card['value']>end($workSpace)['value']){				// Checks if defense card value is higher than attack card's
					$this->defender($player, $index);						// this adds the card to the workspace and remove it from player's hand
				}else
					$this->session->set_userdata('alert', 'Card is of lower value!');
			}else
				$this->session->set_userdata('alert', 'Card is not of the same suit!');
			
			redirect('letsplaydurak');
		}
		
		function defender($player, $index){
			$deckCount = $this->getDeckCount();
			$hand = $player->getHand();
			$this->addToWorkSpace($hand[$index]);					// adds the card to the workspace
			unset($hand[$index]);									// Removes the card from hand
			$player->setHand($hand);
			$HandCount = $player->getHandCount();
			
			$this->setAllPlayers($player);
			if($HandCount==0 && $deckCount==0)
				$this->setWinner($player);
			
			$this->setNextPlayer($player);

			$this->setTurn('Attack');
			$player->setShuffle(false);
			$this->session->set_userdata('alert', 'Player '.$player->getPlayer().' defended successfully!');	
		}
		
		function addToWorkSpace($card){
			$tableTop = $this->session->userdata('workSpace'); 
			array_push($tableTop, $card);
			$this->session->set_userdata('workSpace', $tableTop);
		}
		
		function acceptCards($id){
			$player = $this->getPlayerById($id);
			$nextPlayer = $this->getNextPlayer($player);
			
			$this->session->set_userdata('option', 0);
			$tableTop = $this->session->userdata('workSpace');
			
			$hand = $player->getHand();

			$count = count($tableTop);
			$i=0;
			while($i<$count){													// while workSpace still has cards
				$card = array_pop($tableTop);									// gets the card from the workSpace
				array_push($hand, $card);
				$i++;
			}
			
			$this->deck->setAllDeck($this->getDeck());
			$this->session->set_userdata('workSpace', $tableTop);
			
			$player->setHand($hand);
			$deck = $nextPlayer->playHand($this->deck, $nextPlayer->getHandCount());
			$this->setAllPlayers($player);
			$this->setAllPlayers($nextPlayer);
			$this->setNextPlayer($player);
			
			if($this->session->userdata('attackCount')==0){
				$this->setNextPlayer($player);
				$this->setTurn('Attack');
			}else
				$this->session->set_userdata('attackCount', 0);
			$this->setDeck($deck->getAllDeck());
			$this->session->set_userdata('alert', 'Player '.$id.' accepted the cards! You can continue attacking!');
			
			redirect('letsplaydurak');
		}
		
		// gives the opponent the option to attack or to accept the cards
		function endAttack($id){
			if($this->session->userdata('surrender')){						// If opponent surrenders
				$this->session->set_userdata('surrender', 0);				// resets surrender
				$this->acceptCards($this->getNextPlayerIdById($id));		// opponent accepts the cards
			}
				
			$this->setNextPlayerById($id);
			$this->setTurn('Defend');
			$this->session->set_userdata('option', 1);
			$this->session->set_userdata('attackCount', 0);
			
			$this->session->set_userdata('alert', 'Player '.$id.' has ended the attack! Accept the cards or attack?');
			redirect('letsplaydurak');
		}
		
		function backDown($id){
			$this->setNextPlayerById($id);
			
			$this->setTurn('Attack');
			$this->session->set_userdata('surrender', 1);
			$this->session->set_userdata('alert', 'Player '.$id.' failed to defend! You can now add more cards!');
			
			redirect('letsplaydurak');
		}
		
		function fightBack(){
			$this->session->set_userdata('workSpace', []);
			$this->session->set_userdata('option', 0);
			$this->deck->setAllDeck($this->getDeck());
			
			$player = $this->getCurrentPlayer();
			$nextPlayer = $this->getNextPlayer($player);
			
			$this->setTurn('Attack');
			$this->replenish($player);
			$this->replenish($nextPlayer);

			$this->setCurrentPlayer($player);
			$this->session->set_userdata('alert', 'Player '.$player->getPlayer().' is now fighting back!');
			redirect('letsplaydurak');
		}
		
		function replenish($player){
			$count = $player->getHandCount();
			if($count<6){
				$deck = $player->playHand($this->deck, $count);
				$this->setAllPlayers($player);
				$this->setDeck($deck->getAllDeck());
			}
		}
		
		// Necessary so that the object from session array does not return as incomplete class
		function fixObject (&$object){
		  if (!is_object ($object) && gettype ($object) == 'object')
			return ($object = unserialize (serialize ($object)));
		  return $object;
		}
		
	}
?>